home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / Sample Code / Typography Samples / Glyph Layout ƒ / Glyph Layout.c next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  16.2 KB  |  467 lines  |  [TEXT/KAHL]

  1. /**\
  2. |**| =====================================================================
  3. |**|
  4. |**|    Glyph Layout.c
  5. |**|
  6. |**|    This file contains the calls that this sample needs to make
  7. |**|    the QuickDraw GX shell work correctly.
  8. |**|
  9. |**|    QuickDraw GX Libraries Used:
  10. |**|    "color library.c", "font library.c", "graphics debug library.c",
  11. |**|    "layout library.c", "shape library.c", and "transform library.c".
  12. |**|
  13. |**|    ©1992-1994  Apple Computer, Inc.
  14. |**|    All rights reserved.
  15. |**|
  16. |**| =====================================================================
  17. \**/
  18.  
  19.  
  20. #include "QDGX shell.h"
  21. #include "layout routines.h"
  22. #include "layout library.h"
  23.  
  24.  
  25. /**\
  26. |**| ---------------------------------------------------------------------
  27. |**| PROTOTYPES
  28. |**| ---------------------------------------------------------------------
  29. \**/
  30.  
  31. // funtions required by shell
  32.  
  33. void    DoSetup            (void);
  34. void    DoDraw            (WindowPtr wind, Boolean updating);
  35. OSErr    DoCreateNew        (void);
  36. void    DoDispose        (WindowPtr wind);
  37. void    DoIdle            (WindowPtr wind);
  38. void    DoTeardown        (void);
  39. void    DoClick            (WindowPtr wind, Point p);
  40.  
  41. // private functions
  42.  
  43. OSErr    DoWindowInit        (WindowPtr wind);
  44. void    CreateSampleImage    (WindowPtr wind);
  45.  
  46.  
  47. /**\
  48. |**| ---------------------------------------------------------------------
  49. |**| ENUMS
  50. |**| ---------------------------------------------------------------------
  51. \**/
  52. enum { rWindResource = 128 };
  53.  
  54.  
  55. /**\
  56. |**| ---------------------------------------------------------------------
  57. |**| GLOBALS
  58. |**| ---------------------------------------------------------------------
  59. \**/
  60. // If gDebugging = TRUE, graphics library errors and notices will be posted.  This
  61. // functionality will only work with the "debugging" version of QuickDraw GX.
  62. // If the debugging version is not installed, nothing bad will happen, but these
  63. // functions will not work. 
  64.  
  65. Boolean        gDebugging = true;
  66.  
  67. // Set  "gGiveMeValidation" to TRUE if you want receive run-time validation.
  68.  
  69. Boolean        gGiveMeValidation = true;
  70.  
  71.  
  72. // gGraphicsHeapSize sets the size of the graphics heap created by calling the
  73. // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c.  You can determine
  74. // the amount of graphics heap required by using GraphicsBug.  I'm giving it 600K,
  75. // since we need abunch if we have several windows open.
  76.  
  77. long        gGraphicsHeapSize = 600;
  78.  
  79. // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
  80. // override.  This is so that our override can be native PowerPC code if necessary.
  81.  
  82. GXPrintingEventUPP    gOurPrintingOverrideUPP;
  83.  
  84.  
  85.  
  86. /**\
  87. |**| ---------------------------------------------------------------------
  88. |**| DoSetup()
  89. |**| Here's where we initialize any global variables our application needs.
  90. |**| We have only one at this time -- the universal proc pointer for
  91. |**| our printing override.
  92. |**| ---------------------------------------------------------------------
  93. \**/
  94. void DoSetup (void)
  95. {    // Initialize our printing event override UPP
  96.     gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
  97. }
  98.  
  99.  
  100. /**\
  101. |**| ---------------------------------------------------------------------
  102. |**| DoDraw()
  103. |**| Draw the contents of the window.  The first parameter is the window
  104. |**| to draw, and the second parameter is true if we're updating an existing
  105. |**| image.  If that's the case, we don't want to change anything, but
  106. |**| just draw what's already there.
  107. |**| ---------------------------------------------------------------------
  108. \**/
  109. void DoDraw (WindowPtr wind, Boolean updating)
  110. {
  111.      #pragma unused (updating)
  112.      GXDrawShape (GetDocShape(wind));
  113. }
  114.  
  115.  
  116. /**\
  117. |**| ---------------------------------------------------------------------
  118. |**| DoCreateNew()
  119. |**| This routine is called when a window needs to be created.
  120. |**| ---------------------------------------------------------------------
  121. \**/
  122. OSErr DoCreateNew (void)
  123. {
  124.     OSErr        err = noErr;
  125.     WindowPtr    wind;
  126.     
  127. // Get and create our window from the resource fork
  128.  
  129.     wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
  130.  
  131. // Attach a default gxViewPort to it, create and iInitialize our
  132. // private data for it, and add a sample image to its page shape.
  133.  
  134.     if ( wind == NULL )
  135.         return (MemError());
  136.  
  137.     GXIgnoreGraphicsNotice(transform_already_set);
  138.     SetDefaultViewPort(GXNewWindowViewPort(wind));            
  139.     GXPopGraphicsNotice();
  140.     
  141.     err = DoWindowInit(wind);
  142.     if ( err != noErr )
  143.         return err;
  144.     
  145.     CreateSampleImage(wind);
  146.     return err;
  147. }
  148.  
  149.  
  150. /**\
  151. |**| ---------------------------------------------------------------------
  152. |**| DoDispose()
  153. |**| This routine is called when a window needs to be disposed of.
  154. |**| ---------------------------------------------------------------------
  155. \**/
  156. void DoDispose (WindowPtr wind)
  157. {
  158.     TH_Doc    doc;
  159.     
  160. // You should always dispose of your GX graphics objects before tossing your window.
  161. // Why?  It's generally good form and this approach guarantees that everything is
  162. // disposed.  If you had not disposed of everything, the call to DisposeWindow should
  163. // dispose of the objects. If you are running the debugging version of QuickDraw GX
  164. // with notices set, you will receive a notice that you had not disposed of everything.
  165. // You can turn notices on in this file by setting gDebugging = TRUE (above).
  166.     
  167.     if ( wind != NULL )
  168.     {
  169.         doc = (TH_Doc)GetWRefCon(wind);        // Remember, this is where we stored our private data.
  170.         GXDisposeShape(GetDocShape(wind));     // Dispose of this doc's shape.
  171.         GXDisposeJob(GetDocJob(wind));        // Dispose of this doc's print job.
  172.         DisposHandle((Handle) doc);            // Dispose of our private data.
  173.         DisposeWindow(wind);                // Dispose of the window.
  174.     }
  175. }
  176.  
  177.  
  178. /**\
  179. |**| ---------------------------------------------------------------------
  180. |**| DoIdle()
  181. |**| This routine is called to do things while idling through the event loop.
  182. |**| ---------------------------------------------------------------------
  183. \**/
  184. void DoIdle (WindowPtr wind)
  185. {
  186. }
  187.  
  188.  
  189. /**\
  190. |**| ---------------------------------------------------------------------
  191. |**| DoTeardown()
  192. |**| This routine is called just before we quit to remove anything 
  193. |**| persistent that might have been setup by DoSetup().
  194. |**| ---------------------------------------------------------------------
  195. \**/
  196. void DoTeardown (void)
  197. {
  198.     DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
  199. }
  200.  
  201.  
  202. /**\
  203. |**| ---------------------------------------------------------------------
  204. |**| DoClick()
  205. |**| ---------------------------------------------------------------------
  206. \**/
  207. void DoClick(WindowPtr window, Point p)
  208. {
  209. }
  210.  
  211.  
  212.  
  213.  
  214.  
  215. /**\
  216. |**| ---------------------------------------------------------------------
  217. |**| DoWindowInit()
  218. |**| In this function we create and initialize the the private document
  219. |**| structure for a new window.  This structure contains the print job and
  220. |**| the shape which is drawn in the window.  We store this data in a handle
  221. |**| and hang it off the window's refCon field for easy retrieval.  By doing
  222. |**| this, rather than using globals, we can create many windows containing
  223. |**| unique print jobs and shapes.
  224. |**| ---------------------------------------------------------------------
  225. \**/
  226. OSErr DoWindowInit (WindowPtr wind)
  227. {
  228.     OSErr    err = noErr;
  229.     gxJob    docJob;
  230.     gxShape    docPage;
  231.     TH_Doc    windDoc;
  232.  
  233.  
  234. // Create the page shape. We set the unique items attribute to make sure that each item
  235. // added to the picture has a unique reference. If this attribute was not set, we would
  236. // not see all copies of anything we add to the shape multiple times -- we'd just see
  237. // the last version added.        
  238.  
  239.     docPage = GXNewShape(gxPictureType);
  240.     GXSetShapeAttributes(docPage, (GXGetShapeAttributes(docPage) | gxUniqueItemsShape));
  241.     
  242.     
  243. // Create a print job for this document.  This will be the same as the system default until
  244. // the user goes through the dialogs for Page Setup or Print…
  245.  
  246.     err = GXNewJob(&docJob);
  247.     
  248.     
  249. // If there are no errors, create a handle the size of our document structure and store
  250. // the print job and page shape in it.  Store the handle in the window's refCon field so
  251. // that we can get at it.  (Note that the utility routines "GetDocJob" and "GetDocShape"
  252. // can be used to do this easily.
  253.  
  254.     if ( err == noErr )
  255.     {
  256.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  257.  
  258.         if ( windDoc == NULL )
  259.             err = MemError();
  260.         else
  261.         {
  262.             (*windDoc)->docJob = docJob;
  263.             (*windDoc)->docPage = docPage;
  264.             SetWRefCon(wind, (long) windDoc);
  265.         }
  266.  
  267. // Now install our application override for PrintingEvent so that we can
  268. // support the new movable-modal printing dialog boxes.
  269.  
  270.         GXInstallApplicationOverride(docJob, gxPrintingEvent, gOurPrintingOverrideUPP);
  271.  
  272.     }
  273.  
  274.     return err;
  275. }
  276.  
  277.  
  278. /**\
  279. |**| ---------------------------------------------------------------------
  280. |**| CreateSampleImage()
  281. |**| This function creates primitive shapes and adds them to the window's page shape.
  282. |**| ---------------------------------------------------------------------
  283. \**/
  284. void CreateSampleImage (WindowPtr wind)
  285. {
  286.     Rect    ourWindowRect = wind->portRect; // the rectangle for this window
  287.                                             // in QuickDraw coordinates
  288.     
  289.     gxRunControls     runControls;        // a default run controls structure
  290.     
  291.     gxShape         layout;                // the layout shape we're creating
  292.     gxShape            glyphs;                // the glyph shape holding glyphs from our layout
  293.     gxShape         thePage;            // this window's page shape
  294.     gxLayoutOptions layoutOptions;        // a default layout options structure
  295.     gxStyle         glyphStyles[3];        // an array of styles to use building our layout
  296.     char *            text1 = "Aetna ";    // text of the first run
  297.  
  298. // The text of the second run is "Arabic Macintosh" in Arabic: */
  299. // meem, alif, kaf,  noon, tah,  wau,  shin, <sp>, alif, lam,  ein,  reh,  beh,  yeh 
  300.  
  301.     static char     text2[] =     {0xE5, 0xC7, 0xE3, 0xE6, 0xCA, 0xE8, 0xD4,
  302.                                  0x20, 0xC7, 0xE4, 0xD9, 0xD1, 0xC8, 0xEA, 0};
  303.  
  304.     char *            text3 = " Office AWAY.";    // the text of the third run
  305.     char *            textRuns[3];        // array to hold the three text runs
  306.     short             textLengths[3];        // array to hold the lengths of each run
  307.     short             totalLength;        // the length of all runs together
  308.     gxPoint         posn;                // position of the layout shape
  309.     gxGlyphcode     layoutGlyphs[35];    // array to hold glyph codes of glyphs from layout
  310.     gxPoint         layoutPositions[35]; // array to hold locations of glyphs from layout
  311.     gxPoint         layoutTangents[35]; // array to hold tangents of glyphs from layout
  312.     long             layoutGlyphCount;    // the count of glyphs in the layout
  313.     long             layoutAdvance[2];    // an array of advance bits for glyphs from layout
  314.     long             layoutRuns;            // the number of style runs found in the layout
  315.     short             layoutRunCounts[3];    // array of number of glyphs in each style run
  316.     short             level0 = 0;            // a variable to hold zero (we need its address)
  317.     gxStyle         layoutStyles[3];    // array to receive styles found in layout shape
  318.  
  319. // Initialize the array of text runs for our layout shape
  320.  
  321.     textRuns[0] = text1;
  322.     textRuns[1] = text2;
  323.     textRuns[2] = text3;
  324.     
  325. // Initialize the text lengths.
  326.  
  327.     textLengths[0] = MyStrLength(text1);
  328.     textLengths[1] = MyStrLength(text2);
  329.     textLengths[2] = MyStrLength(text3);
  330.     
  331.     totalLength = textLengths[0] + textLengths[1] + textLengths[2];
  332.  
  333. // Use library routines to initialize default gxLayoutOptions and gxRunControls structures
  334.  
  335.     InitializeLayoutOptions (&layoutOptions);
  336.     InitializeRunControls (&runControls);
  337.     
  338. // Position the layout almost half way down the left edge of the window. Set 
  339. // the layout's width to the window's width and set the flushness to 1/2, this
  340. // will cause the layout to center in the window.  Note that ourWindowRect is
  341. // not in fixed coordinates, so we have to make it fixed to use it.
  342.  
  343.     layoutOptions.width = ff(ourWindowRect.right - ourWindowRect.left);
  344.     layoutOptions.flush = fract1/2;
  345.  
  346.     posn.x = 0;
  347.     posn.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2) - ff(25);
  348.     
  349.  
  350. // Use the library routines to initialize three style runs.  The first one is 38-point
  351. // Helvetica.  NewLayoutStyle is found in layout library.c.
  352.  
  353.     glyphStyles[0] = NewLayoutStyle(
  354.         (char *) "\pHelvetica",            // the gxFontName for the style
  355.         ff(38),                            // the point size in fixed point
  356.         0,                                // gxTextAttributes (none)
  357.         &runControls,                    // our default run controls
  358.         nil,                            // run features (none for us)
  359.         0,                                // count of run features
  360.         nil);                            // style run overrides (none for us)
  361.  
  362. // The second one is 38-point Baghdad.
  363.  
  364.     glyphStyles[1] = NewLayoutStyle(
  365.         (char *) "\pBaghdad Plain",        // the gxFontName for the style
  366.         ff(38),                            // the point size in fixed format
  367.         0,                                // gxTextAttributes (none)
  368.         &runControls,                    // our default run controls
  369.         nil,                            // run featuers (none for this style)
  370.         0,                                 // count of run features
  371.         nil);                            // style run overrides (none for us)
  372.     
  373. // The third and final one is 38-point Times Roman
  374.  
  375.     glyphStyles[2] = NewLayoutStyle(
  376.         (char *) "\pTimes Roman",        // the gxFontName for this style
  377.         ff(38),                            // the point size (fixed format)
  378.         0,                                // no gxTextAttributes
  379.         &runControls,                    // our default run controls
  380.         nil,                            // no run features
  381.         0,                                // count of no run features = 0
  382.         nil);                            // style run overrides (still none)
  383.     
  384. // We're ready to build our layout now!
  385.  
  386.     layout = GXNewLayout(
  387.         3,                                    // count of text runs
  388.         textLengths,                        // array of lengths of each run
  389.         (void *)textRuns,                    // array of pointers to the text
  390.         3,                                    // count of style runs
  391.         textLengths,                        // array of the byte lengths of each run
  392.         glyphStyles,                        // array of the styles
  393.         1,                                    // number of levels in the layout
  394.         &totalLength,                        // array of lengths of levels (only one)
  395.         &level0,                            // array of the levels (only one)
  396.         &layoutOptions,                        // options (default)
  397.         &posn);                                // position of the layout shape (none)
  398.         
  399. // Now that we have a layout shape, we show how to get glyphs back from it.
  400. // We can do this several ways.  One easy way is to call GXPrimitiveShape on
  401. // the layout shape, which changes it permanently to a glyph shape.  Of course,
  402. // then you can't change it back to a layout.  A non-destructive way is to call
  403. // GXGetLayoutGlyphs, which gives us back a glyph shape as well as all kinds of
  404. // wonderfully useful information about the layout shape's geometry.
  405.  
  406.     GXIgnoreGraphicsNotice(glyph_tangents_have_no_effect);        // we don't care
  407.     layoutGlyphCount = GXGetLayoutGlyphs(
  408.         layout,                                // the layout to get glyphs from
  409.         layoutGlyphs,                        // an array of glyph codes we're getting
  410.         layoutPositions,                    // the positions of each glyph in the array
  411.         layoutAdvance,                        // the advance bits for all the glyphs
  412.         layoutTangents,                        // the tangents for all the glyphs
  413.         &layoutRuns,                        // the number of style runs in the layout
  414.         layoutRunCounts,                    // the number of glyphs in each style run
  415.         layoutStyles);                        // the styles from the layout shape
  416.     GXPopGraphicsNotice();
  417.     
  418. // Now we're going to make a new glyph shape that reflects all this information.
  419. // After creating a new glyph shape, we set the gxIgnorePlatformShape attribute
  420. // bit on it.  Why?  That tells QuickDraw GX to interpret the "text" we're sending
  421. // to layout not as ASCII or any other platform or script, but instead as actual
  422. // glyph offsets, which is what we got back from GXGetLayoutGlyphs.  Then we're
  423. // ready to stuff our shape full of the glyph information we got.  Remember that
  424. // a single glyph shape can draw multiple glyphs.
  425.  
  426.     glyphs = GXNewShape(gxGlyphType);
  427.     GXSetShapeAttributes(glyphs, GXGetShapeAttributes(glyphs) | gxIgnorePlatformShape);
  428.  
  429.     GXSetGlyphs(
  430.         glyphs,                                // the glyph shape to set
  431.         layoutGlyphCount,                    // the count of glyphs we're setting in
  432.         (unsigned char *) layoutGlyphs,        // the glyph codes (the "text")
  433.         layoutPositions,                    // the positions of each glyph
  434.         layoutAdvance,                        // the advance bits for each glyph
  435.         layoutTangents,                        // the tangents for each glyph
  436.         layoutRunCounts,                    // the number of glyphs in each style run
  437.         layoutStyles);                        // the style runs
  438.  
  439. // Move the new shape down vertically 50 pixels so it doesn't overlap the layout shape.
  440. // Since we're using the same positions we got from the layout shape, failure to move
  441. // the new glyph shape would make them draw right on top of each other.
  442.  
  443.     GXMoveShape(glyphs, 0, ff(50));
  444.  
  445. // Get this window's page shape and add our layout and glyph shapes to it.
  446.  
  447.     thePage = GetDocShape(wind);
  448.     
  449.     AddToShape(thePage, layout);
  450.     AddToShape(thePage, glyphs);
  451.     
  452. // Dispose of all the stuff we created
  453.  
  454.     GXDisposeShape(layout);
  455.     GXDisposeShape(glyphs);
  456.     GXDisposeStyle(glyphStyles[0]);
  457.     GXDisposeStyle(glyphStyles[1]);
  458.     GXDisposeStyle(glyphStyles[2]);
  459.  
  460.  
  461. // Invalidate the window's portRect so that everything gets updated.
  462.     
  463.     SetPort(wind);
  464.     InvalRect(&ourWindowRect);
  465. }
  466.  
  467.